package cate.game.role.login.msg;

import cate.common.table.d.GDBlog;
import cate.game.GameBody;
import cate.game.chat.ChatRequest;
import cate.game.client.ClientContext;
import cate.game.client.msg.ClientMsg;
import cate.game.client.msg.MsgConfig;
import cate.game.client.msg.MsgInput;
import cate.game.client.msg.id.MsgIdBLogin;
import cate.game.event.master.RoleLoginEvent;
import cate.game.role.Role;
import cate.game.role.login.RoleCreateParam;
import cate.game.util.api.ChatApi;
import cate.game.util.api.ConsoleApi;
import cate.game.util.api.LoginApi;
import cp.solution.business.game.role.NameRegEntity;
import cp.solution.business.sys.account.AccountEntity;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@ClientMsg(title = "创建新角色 の 请求")
public class RoleCreateReq extends RoleCreateParam implements MsgInput {

    private static final long ACTION_INTERVAL = 5000l;
    /** 操作行为记录 */
    private static Map<Integer, Long> actionRecord = new HashMap<>();

    @NoteField(value = "名字内容验证")
    public String checkSign;

    @Override
    public MsgConfig conf() {
        return MsgIdBLogin.CREATE_ROLE_REQ;
    }

    @Override
    public void execute(GameBody game, ClientContext cc) {
        this.fix();
        RoleCreateResp resp = new RoleCreateResp();
        if(cc.getLoginData() == null) {
            resp.code = RoleCreateResp.CODE_PLEASE_RE_LOGIN;
            resp.message = "请重新登录";//"please re login";
            cc.sendNow(resp);
            return;
        }

        final int accountId = cc.getLoginData().getAccount().getId();
        final Long actionTs = actionRecord.get(accountId);
        final long now = System.currentTimeMillis();
        if(actionTs != null && now - actionTs < ACTION_INTERVAL) {
            resp.code = RoleCreateResp.CODE_ACTION_REPEAT;
            resp.message = "角色正在创建中，请勿重复操作";
            cc.sendNow(resp);
            return;
        }
        actionRecord.put(accountId, now);
        // ThreadUtils.sleep(4000);//故意卡住测试一下。

        if(cc.getRole() != null){
            resp.code = RoleCreateResp.CODE_PLEASE_RE_LOGIN;
            resp.message = "请重新登录";
            cc.sendNow(resp);
            actionRecord.remove(accountId);
            return;
        }
        if(game.config.gs.getRoleMax() > 0 && game.stat.gameHandler.getRoleNum() > game.config.gs.getRoleMax()) {
            resp.code = RoleCreateResp.CODE_ROLE_MAX_REACHED;
            resp.message = "角色数达到上限，请换其他服创角";//"role max reached";
            cc.sendNow(resp);
            actionRecord.remove(accountId);
            return;
        }
        if( name == null || name.length() < GDBlog.NAME_LENGTH_MIN || name.length() > GDBlog.NAME_LENGTH_MAX) {
            resp.code = RoleCreateResp.CODE_NAME_FORMAT_ERR;
            resp.message = "名字格式错误";//"name format err";
            cc.sendNow(resp);
            actionRecord.remove(accountId);
            return;
        }
        if(!game.tools.sensitiveWords.legal(this.name)) {
            resp.code = RoleCreateResp.CODE_NAME_ILLEGAL;
            resp.message = "名字包含敏感词汇";//"name illegal";
            cc.sendNow(resp);
            actionRecord.remove(accountId);
            return;
        }
        synchronized (cc) {
            String uid = ObjectId.get().toHexString();
            Role role = new Role(game, uid);
            AccountEntity account = cc.getLoginData().getAccount();
            role.getBase().accountId = account.getId();
            role.getBase().read(cc.getLoginData());
            role.getBase().name = this.name;
            role.getBase().sex = this.sex;
            role.getBase().langCode = this.langCode;
            role.getBase().srvIdOrigin = game.config.srvId;
            if(StringUtils.isBlank(role.getBase().visitorId)) {
                role.getBase().visitorId = this.visitorId;
            }
            role.getStatus().createTime = System.currentTimeMillis();
            try {
                if(StringUtils.isNotBlank(checkSign)) {
                    ChatRequest.checkSign(this.name, checkSign);
                } else {
                    if(!game.tools.sensitiveWords.legal(this.name)) {
                        resp.code = RoleCreateResp.CODE_NAME_ILLEGAL;
                        resp.message = "请换个名字";//"名字包含敏感词汇";//"name illegal";
                        cc.sendNow(resp);
                        actionRecord.remove(accountId);
                        return;
                    }
                }
                EcResult r = ChatApi.checkRoleName(role, this.name);
                if(!r.ok()) {
                    resp.code = RoleCreateResp.CODE_NAME_ILLEGAL;
                    resp.message = r.message;//"名字包含敏感词汇";//"name illegal";
                    cc.sendNow(resp);
                    actionRecord.remove(accountId);
                    return;
                }
            } catch (Exception e) {
                resp.code = RoleCreateResp.CODE_NAME_ILLEGAL;
                resp.message = "fail on call yzx api";//"名字包含敏感词汇";//"name illegal";
                cc.sendNow(resp);
                actionRecord.remove(accountId);
                return;
            }
            try {
                ConsoleApi.regName(game, role, NameRegEntity.REG_TYPE_CREATE);
            } catch (Exception e) {
                resp.send(cc, RoleCreateResp.CODE_REG_NAME_FAIL, e.getMessage(), null);
                actionRecord.remove(accountId);
                return;
            }
            try {
                LoginApi.regToLogin(game, role);
            } catch (Exception e) {
                resp.send(cc, RoleCreateResp.CODE_REG_LOGIN_FAIL, e.getMessage(), null);
                actionRecord.remove(accountId);
                return;
            }
            // 小程序分享登录码设置
            role.getBase().invite.setCreateCode(this.inviteCode);
            role.getBase().invite.setLoginCode(this.inviteCode);
            game.stat.gameHandler.addRoleNum();
            role.newAllPart();
            role.onCreate();
            cc.bindRole(role, game);
            game.eventDispatcher.dispatchEvent(new RoleLoginEvent(role, true));
            game.stat.whenLogin(role);
            resp.code = RoleCreateResp.CODE_DONE;
            resp.message = "done";
            resp.roleId = uid;
            cc.sendNow(resp);

            actionRecord.remove(accountId);
        }
    }
}
